## Hadamard matrix of a finite field

from PyM import *

def paley_matrix(F):
    if characteristic(F)==2:
        return "paley_matrix error: the characteristic of F must not be 2"
    q = cardinal(F)
    def x(j): return element(j,F)
    def chi(a): return legendre(a,F)
    return matrix([[chi(x(i)-x(j)) for j in range(q)] for i in range(q)])

def hadamard_matrix_paley(K):
    q = cardinal(K)
    if q%4 != 3:
        return "hadamard_matrix_FF Error: {} is not 3 mod 4".format(q)
    A = I_(q,Z_) + paley_matrix(K)
    u = matrix(q*[1])
    x = splice(matrix([1]),u)
    X = splice(transpose(u),-A)
    return stack(x,X)

def conference_matrix(K):
    q = cardinal(K)
    e = ((q-1)//2)%2
    e = (-1)**e
    S = paley_matrix(K)
    u = matrix(q*[1])
    x = splice(matrix([0]),u)
    X = splice(transpose(e*u),S)
    return stack(x,X)

def hadamard_matrix_finite_field(K):
    q = cardinal(K)
    e = ((q-1)//2)%2
    #e = (-1)**e
    I = I_(q+1,Z_); Im=-I_(q+1,Z_)
    C = conference_matrix(K)
    if e==0:
        return stack(splice(I+C,Im+C),splice(Im+C,Im-C))
    return hadamard_matrix_paley(K)


show(hadamard_matrix_finite_field(Zn(7)))
    
show(hadamard_matrix_finite_field(Zn(5)))

[F,x] = extension(Zn(3),[1,0,1],'x')

show(hadamard_matrix_finite_field(F))